package com.webank.wedatasphere.qualitis.controller.thymeleaf;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.webank.wedatasphere.qualitis.project.dao.repository.ProjectApprovedRepository;
import com.webank.wedatasphere.qualitis.project.dao.repository.ProjectMuLuRepository;
import com.webank.wedatasphere.qualitis.project.dao.repository.ProjectRelationShipRuleRepository;
import com.webank.wedatasphere.qualitis.project.dao.repository.ProjectRepository;
import com.webank.wedatasphere.qualitis.project.entity.*;
import com.webank.wedatasphere.qualitis.response.Grid;
import com.webank.wedatasphere.qualitis.response.Resp;
import com.webank.wedatasphere.qualitis.rule.dao.repository.RuleRepository;
import com.webank.wedatasphere.qualitis.rule.entity.RuleDetailInfoVo;
import com.webank.wedatasphere.qualitis.util.LocalTimeUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = {"/biaozhun"})
public class BiaoZhunController {

    /**
     * 规则操作
     */
    @Autowired
    private RuleRepository ruleRepository;


    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private ProjectMuLuRepository projectMuLuRepository;


    @Autowired
    private ProjectApprovedRepository projectApprovedRepository;

    @Autowired
    private ProjectRelationShipRuleRepository projectRelationShipRuleRepository;

    /**
     * Layui 分页
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/pageIndex"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> getCountIndex(HttpServletRequest request) {
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        //  分页查询
        String page = request.getParameter("page");
        String limit = request.getParameter("limit");
        Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, Integer.parseInt(limit), sort);
        Page<Project> all = projectRepository.findAll(pageable);
        List<ProjectMuLu> muLuRepositoryAll = projectMuLuRepository.findAll();
        // 更新目录树
        for (Project project : all) {
            String sjzlbzml = project.getSjzlbzml();
            for (ProjectMuLu muLu : muLuRepositoryAll) {
                if (String.valueOf(muLu.getId()).equals(sjzlbzml)) {
                    project.setSjzlbzml(muLu.getTitle());
                }
            }
        }
        List<Project> content = all.getContent();
        long totalElements = all.getTotalElements();
        Resp<List<Project>> resp = Resp.OkPage(content, totalElements);
        resp.setCode(0);
        return resp;
    }

    /**
     * 测试账列表
     *
     * @return
     */
    @RequestMapping(value = {"/list"}, method = RequestMethod.GET)
    public ModelAndView list(HttpServletRequest request) {
        ModelAndView modelAndView = new ModelAndView("layui-admin/sjbz/list");
        modelAndView.addObject("BiaoZunMuID", request.getParameter("muluId"));
        return modelAndView;
    }

    /**
     * 正式账列表
     *
     * @return
     */
    @RequestMapping(value = {"/formalSJBZ"}, method = RequestMethod.GET)
    public ModelAndView formalSJBZ(HttpServletRequest request) {
        ModelAndView modelAndView = new ModelAndView("layui-admin/sjbz/formalSJBZ");
        modelAndView.addObject("BiaoZunMuID", request.getParameter("muluId"));
        return modelAndView;
    }


    /**
     * 新增
     *
     * @param httpServletRequest
     * @return
     */
    @RequestMapping(value = {"/detail"}, method = RequestMethod.GET)
    public ModelAndView insertsjbz(HttpServletRequest httpServletRequest) {
        ModelAndView view = new ModelAndView("layui-admin/sjbz/detail");
        String id = httpServletRequest.getParameter("id");
        if (StringUtils.isNotBlank(id)) {
            Project dataInfo = projectRepository.getOne(Long.parseLong(id));
            List<ProjectApproved> approvalList = projectApprovedRepository.findByApprovedBiaoZunId(dataInfo.getId());
            view.addObject("dataInfo", dataInfo);
            view.addObject("approvalList", approvalList);
        } else {
            view.addObject("dataInfo", new Project());
            view.addObject("approvalList", new ArrayList<ProjectApproved>());
        }
        return view;
    }

    @RequestMapping(value = {"/remove"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @Transactional
    public Resp<DataSourcePoJo> remove(HttpServletRequest request) {
        String ids = request.getParameter("ids");
        if (StringUtils.isNotBlank(ids)) {
            String[] split = ids.split(",");
            for (String id : split) {
                if (StringUtils.isNotBlank(id)) {
                    projectRepository.deleteById(Long.valueOf(id));
                }
            }
        }
        return Resp.Ok();
    }

    /**
     * EasyUI分页
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/datagrid"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Grid<?> datagrid(HttpServletRequest request) {
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        //  分页查询
        String page = request.getParameter("page");
        String limit = request.getParameter("rows");
        // 获取条件过滤器
        JSONObject changeBuilder = getJsonObject(request);
        // 组装SQl条件过滤法器
        ExampleMatcher matcher = getSqlWhere(request);
        // 序列化对象
        Project itemQueryWhere = changeBuilder.toJavaObject(Project.class);
        // 条件过滤
        if (StringUtils.isNotBlank(request.getParameter("sjzlbzml")) && !request.getParameter("sjzlbzml").equals("null")) {
            itemQueryWhere.setSjzlbzml(request.getParameter("sjzlbzml"));
        }
        if (StringUtils.isNotBlank(request.getParameter("onlySuccess")) && !request.getParameter("onlySuccess").equals("null")) {
            itemQueryWhere.setFbzt("已发布");
        }
        // 分页插件
        Pageable pageable = PageRequest.of(Integer.parseInt(page) - 1, Integer.parseInt(limit), sort);
        // 条件过滤器插件
        Example<Project> example = Example.of(itemQueryWhere, matcher);
        // 条件过滤+分页
        Page<Project> all = projectRepository.findAll(example, pageable);
        // 获取目录翻译所属目录
        List<ProjectMuLu> muLuRepositoryAll = projectMuLuRepository.findAll();
        for (Project project : all) {
            for (ProjectMuLu projectMuLu : muLuRepositoryAll) {
                if (StringUtils.isNotBlank(project.getSjzlbzml()) && project.getSjzlbzml().equals(projectMuLu.getId().toString())) {
                    project.setSjzlbzml(projectMuLu.getTitle());
                }
            }
        }
        List<Project> content = all.getContent();
        long totalElements = all.getTotalElements();
        return Grid.OkPage(CollectionUtils.isEmpty(content)?new ArrayList<>():content,totalElements);
    }


    public static JSONObject getJsonObject(HttpServletRequest request) {
        JSONObject changeBuilder = new JSONObject();
        String filterRules = request.getParameter("filterRules");
        if (StringUtils.isNotEmpty(filterRules)) {
            JSONArray filters = JSONArray.parseArray(filterRules);
            for (int i = 0; i < filters.size(); i++) {
                JSONObject item = filters.getJSONObject(i);
                changeBuilder.put(item.getString("field"), item.getString("value"));
            }
        }
        return changeBuilder;
    }

    public static ExampleMatcher getSqlWhere(HttpServletRequest request) {
        ExampleMatcher withMatcher = ExampleMatcher.matching();
        String filterRules = request.getParameter("filterRules");
        if (StringUtils.isNotEmpty(filterRules)) {
            JSONArray filters = JSONArray.parseArray(filterRules);
            for (int i = 0; i < filters.size(); i++) {
                JSONObject item = filters.getJSONObject(i);
                // 模糊匹配
                withMatcher = withMatcher.withMatcher(item.getString("field"), ExampleMatcher.GenericPropertyMatchers.contains());
            }
        }
        return withMatcher;
    }


    /**
     * 关联规则
     *
     * @param request request
     * @param rules   rules
     * @return Resp
     */
    @RequestMapping(value = {"/selectRule"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @Transactional
    public Resp<?> selectRule(HttpServletRequest request, @RequestBody List<RuleDetailInfoVo> rules) {
        try {
            String bzId = request.getParameter("BZId");
            Project project = projectRepository.getOne(Long.parseLong(bzId));
            for (RuleDetailInfoVo rule : rules) {
                ProjectRelationShipRule projectRelationShipRule = new ProjectRelationShipRule();
                projectRelationShipRule.setProjectId(project.getId());
                projectRelationShipRule.setRuleId(rule.getId());
                projectRelationShipRule.setRuleName(rule.getRuleName());
                projectRelationShipRule.setProjectName(project.getCnName());
                projectRelationShipRule.setCreateTime(LocalTimeUtils.getCurrentTimeSimple());
                projectRelationShipRuleRepository.save(projectRelationShipRule);
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return Resp.error(e.getMessage());
        }
        return Resp.Ok();
    }


    @RequestMapping(value = {"/getMuluSelect"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> getMuluSelect() {
        List<ProjectMuLu> content = projectMuLuRepository.findAll();
        return Resp.Ok(content);
    }

    /**
     * 移除关联规则
     * @return
     */
    @RequestMapping(value = {"/removeRelationShipRule"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @Transactional
    public Resp<?> removeRelationShipRule(HttpServletRequest request) {
        String ruleId = request.getParameter("ruleId");
        String projectId = request.getParameter("projectId");
        projectRelationShipRuleRepository.deleteByProjectIdAndRuleId(Long.parseLong(projectId),Long.parseLong(ruleId));
        return Resp.Ok();
    }


    @RequestMapping(value = {"/mulu"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> projectMuLuRepositoryGet() {
        List<ProjectMuLu> allList = projectMuLuRepository.findAll();
        List<ProjectMuLu> treeList = allList.stream().filter(parentNode -> parentNode.getParentId() == 0L)
                .map(node -> getChild(node, allList)).collect(Collectors.toList());
        return Resp.Ok(treeList);
    }

    @RequestMapping(value = {"/muluDel"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> muluDel(@RequestParam("id") long id) {
        List<ProjectMuLu> list = projectMuLuRepository.findThisChild(id);
        if (CollectionUtils.isEmpty(list)) {
            projectMuLuRepository.deleteById(id);
            return Resp.Ok();
        }
        return Resp.error("删除失败，请先删除子级");
    }

    @RequestMapping(value = {"/muluUpdate"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> muluUpdate(@RequestBody Map<String, Object> map) {
        String id = map.get("id").toString();
        if (StringUtils.isBlank(id)) {
            String jsonString = JSONObject.toJSONString(map);
            return muluAdd(JSONObject.parseObject(jsonString, ProjectMuLu.class));
        }
        ProjectMuLu one = projectMuLuRepository.getOne(Long.parseLong(id));
        one.setTitle(map.get("title").toString());
        projectMuLuRepository.save(one);
        return Resp.Ok();
    }

    /**
     * 标准添加
     *
     * @param map
     * @return
     */
    @RequestMapping(value = {"/biaozunAdd"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> biaozunAdd(@RequestBody Map<String, Object> map) {
        try {
            String jsonString = JSONObject.toJSONString(map);
            Project project = JSONObject.parseObject(jsonString, Project.class);
            project.setCreateTime(LocalTimeUtils.getCurrentTimeSimple());
            project.setCreateUser("admin");
            project.setProjectType(1);
            project.setFbzt("未发布");
            project.setCreateUserFullName("admin(管理员)");
            project.setDescription(project.getName() + "-类型：" + project.getSjzllx());
            projectRepository.save(project);
        } catch (Exception e) {
            e.printStackTrace();
            return Resp.error(e.getMessage());
        }
        return Resp.Ok();
    }

    /**
     * 标准编辑修改
     *
     * @param map
     * @return
     */
    @RequestMapping(value = {"/biaozunUpdate"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> biaozunUpdate(@RequestBody Map<String, Object> map) {
        try {
            String jsonString = JSONObject.toJSONString(map);
            Project project = JSONObject.parseObject(jsonString, Project.class);
            project.setCreateTime(LocalTimeUtils.getCurrentTime());
            project.setCreateUser("admin");
            project.setProjectType(1);
            project.setCreateUserFullName("admin(管理员)");
            project.setDescription(project.getName() + "-类型：" + project.getSjzllx());
            project.setModifyTime(LocalTimeUtils.getCurrentTime());
            projectRepository.save(project);
        } catch (Exception e) {
            e.printStackTrace();
            return Resp.error(e.getMessage());
        }
        return Resp.Ok();
    }

    /**
     * 标准编辑修改--发布
     *
     * @param project
     * @return
     */
    @RequestMapping(value = {"/modifyStatus"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @Transactional
    public Resp<?> biaozunUpdate(HttpServletRequest request, @RequestBody Project project) {
        String operation = request.getParameter("operation");
        try {
            switch (operation) {
                case "FBZ":
                    if (project.getFbzt().equals("发布中")) {
                        return Resp.error("项目已提交发布申请，不能重复提交发布申请");
                    }
                    project.setFbzt("发布中");
                    projectApproved(project, "提交申请", "admin");
                    break;
                case "YFB":
                    project.setFbzt("已发布");
                    projectApproved(project, "审批通过", "admin");
                    break;
                case "WFB":
                    project.setFbzt("未发布");
                    projectApprovedRepository.deleteByApprovedBiaoZunId(project.getId());
                    break;

            }
            projectRepository.updateStatusFBSuccess(project.getId(), project.getFbzt(), LocalTimeUtils.getCurrentTime());
        } catch (Exception e) {
            e.printStackTrace();
            return Resp.error(e.getMessage());
        }
        return Resp.Ok();
    }

    private void projectApproved(Project project, String status, String userName) {
        // 进入审批流
        List<ProjectApproved> byApprovedBiaoZunId = projectApprovedRepository.findByApprovedBiaoZunId(project.getId());
        Long approvedVersion = 1L;
        if (CollectionUtils.isNotEmpty(byApprovedBiaoZunId)) {
            // 获取审批流中最新的一条
            ProjectApproved projectApproved = byApprovedBiaoZunId.stream().min((o1, o2) -> o2.getApprovedVersion().compareTo(o1.getApprovedVersion())).get();
            approvedVersion = projectApproved.getApprovedVersion() + 1;
        }
        ProjectApproved projectApproved = new ProjectApproved();
        projectApproved.setApprovedMsg(status);
        projectApproved.setApprovedBiaoZunId(project.getId());
        projectApproved.setApprovedTime(LocalTimeUtils.getCurrentTime());
        projectApproved.setApprovedOperation(status);
        projectApproved.setApprovedUser(userName);
        projectApproved.setApprovedVersion(approvedVersion);
        projectApprovedRepository.save(projectApproved);
    }

    @RequestMapping(value = {"/muluAdd"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Resp<?> muluAdd(@RequestBody ProjectMuLu projectMuLu) {
        projectMuLu.setParentId(projectMuLu.getParentId());
        projectMuLu.setName(projectMuLu.getTitle());
        projectMuLu.setSpread("true");
        projectMuLu.setId(null);
        projectMuLuRepository.save(projectMuLu);
        return Resp.Ok();
    }

    /**
     * 递归辅助函数
     *
     * @param sql     上级节点
     * @param allList 所有数据
     */
    public ProjectMuLu getChild(ProjectMuLu sql, List<ProjectMuLu> allList) {
        /**
         * 1、filter：获取子节点pid是否等于id
         * 2、map：递归获取子节点
         * */
        List<ProjectMuLu> treeSQL = allList.stream()
                .filter(subNode -> subNode.getParentId().equals(sql.getId()))
                .map(subNode -> getChild(subNode, allList)).collect(Collectors.toList());
        sql.setChildren(treeSQL);
        return sql;
    }

}
